package com.lst.tools.quartz.config;

import com.lst.tools.quartz.properties.QuartzProperties;
import org.quartz.Scheduler;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;

/**
 * Quartz调度配置类
 *
 * @author: Frank
 * @date: 2019/09/24 13:51
 * @version: V1.0
 */
@Configuration
public class QuartzScheduledConfig {

    @Autowired
    private QuartzProperties quartzProperties;
    @Autowired
    private DataSource dataSource;

    @Bean
    public JobFactory jobFactory(ApplicationContext applicationContext) {
        AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        return jobFactory;
    }

    /**
     * 如果需要加载写好的CronTrigger，使用这种方式
     *
     * @param jobFactory
     * @param cronTrigger
     * @param jobDetails
     * @return
     */
    @Bean(destroyMethod = "destroy", autowire = Autowire.NO)
    //todo
    //public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory, CronTrigger[] cronTrigger, JobDetail[] jobDetails) {
    public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) {
        SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
        factoryBean.setQuartzProperties(quartzProperties.getQuartzProperties());
        factoryBean.setDataSource(dataSource);
        factoryBean.setJobFactory(jobFactory);
        //todo
        //factoryBean.setTriggers(cronTrigger);
        //todo
        //factoryBean.setJobDetails(jobDetails);
        //使job实例支持spring 容器管理
        factoryBean.setOverwriteExistingJobs(true);
        // 延迟10s启动quartz
        factoryBean.setStartupDelay(10);
        return factoryBean;
    }

    @Bean(initMethod = "start", destroyMethod = "shutdown")
    public Scheduler scheduler(SchedulerFactoryBean schedulerFactoryBean) {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        return scheduler;
    }

    @Component
    class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

        private transient AutowireCapableBeanFactory beanFactory;

        @Override
        public void setApplicationContext(final ApplicationContext context) {
            beanFactory = context.getAutowireCapableBeanFactory();
        }

        /**
         * 将job实例交给spring ioc托管
         * 我们在job实例实现类内可以直接使用spring注入的调用被spring ioc管理的实例
         *
         * @param bundle
         * @return
         * @throws Exception
         */
        @Override
        protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
            final Object job = super.createJobInstance(bundle);
            beanFactory.autowireBean(job);
            return job;
        }
    }
}
